#include "S1.h"
#include "E1.h"
#include "S7.h"
#include "S2.h"
#include "i2c.h"
#include "systick.h"
#include "gd32f4xx_it.h"


#define LED_WHITE 1
#define LED_WARM 2
#define LED_FLASH 3
#define LED_CLOSE 4
#define LED_BODY 5

#define SHINE_MAX 114
#define SCALE 26

i2c_addr_def KEY_addr;      // Key address struct
i2c_addr_def LED_addr;      // LED address struct
i2c_addr_def TUBE_addr;     // TUBE address struct
i2c_addr_def BH1750_addr;   // BH1750 address struct
i2c_addr_def S7_addr;

uint16_t LED_pwm;
uint8_t LED_flag = LED_CLOSE;
uint8_t LED_flash;

uint8_t have_people = 0;
uint8_t s7_sleep_time = 0;

float ss_value;

void led_control(uint8_t mode);

int main(void)
{

    init_i2c();

    // init e1 and s1 and s7
    KEY_addr = s1_init(HT16K33_ADDRESS_S1);
    LED_addr = e1_init(PCA9685_ADDRESS_E1);
    TUBE_addr = e1_init(HT16K33_ADDRESS_E1);
    BH1750_addr = s2_init(BH1750_ADDRESS_S2);
    S7_addr = s7_init(PCA9557_ADDRESS_S7);

    systick_config();   //system tick configuration

    TIMER1_Init();
    TIMER2_Init();
    TIMER3_Init();

    while (1)
    {
        led_control(key_trans(KEY_addr));    //take action
        delay_1ms(50);
    }
}

void led_control(uint8_t mode){	//Control over target LED
    switch(mode)
    {
        case LED_WHITE:
            LED_flash = 0;
            s7_sleep_time = LED_flag == LED_BODY ? 10 : s7_sleep_time;
            have_people = 0;
            LED_flag = LED_WHITE;
            nvic_irq_disable(TIMER1_IRQn);
            setPWM(LED_addr.periph, LED_addr.addr, LED_R, 0x0000, 0x0C00);
            setPWM(LED_addr.periph, LED_addr.addr, LED_G, 0x0000, 0x0C00);
            setPWM(LED_addr.periph, LED_addr.addr, LED_B, 0x0000, 0x0C00);
            break;
        case LED_WARM:
            LED_flash = 0;
            s7_sleep_time = LED_flag == LED_BODY ? 10 : s7_sleep_time;
            have_people = 0;
            LED_flag = LED_WARM;
            nvic_irq_disable(TIMER1_IRQn);
            setPWM(LED_addr.periph, LED_addr.addr, LED_R, 0x0000, 0x0C00);
            setPWM(LED_addr.periph, LED_addr.addr, LED_G, 0x0000, 0x0bf1);
            setPWM(LED_addr.periph, LED_addr.addr, LED_B, 0x0000, 0x065d);
            break;
        case LED_FLASH:
            LED_flash = 1;
            s7_sleep_time = LED_flag == LED_BODY ? 10 : s7_sleep_time;
            have_people = 0;
            LED_flag = LED_FLASH;
            nvic_irq_enable(TIMER1_IRQn, 2, 2);
            setPWM(LED_addr.periph, LED_addr.addr, LED_R, 0x0000, LED_pwm);
            setPWM(LED_addr.periph, LED_addr.addr, LED_G, 0x0000, LED_pwm);
            setPWM(LED_addr.periph, LED_addr.addr, LED_B, 0x0000, LED_pwm);
            break;
        case LED_CLOSE:
            LED_flash = 0;
            s7_sleep_time = LED_flag == LED_BODY ? 10 : s7_sleep_time;
            have_people = 0;
            LED_flag = LED_CLOSE;
            nvic_irq_disable(TIMER1_IRQn);
            setPWM_off(LED_addr.periph, LED_addr.addr);
            break;
        default:
            if (LED_flash == 1)
            {
                setPWM(LED_addr.periph, LED_addr.addr, LED_R, 0x0000, LED_pwm);
                setPWM(LED_addr.periph, LED_addr.addr, LED_G, 0x0000, LED_pwm);
                setPWM(LED_addr.periph, LED_addr.addr, LED_B, 0x0000, LED_pwm);
            }
            else if (LED_flag == LED_WHITE && (uint16_t)ss_value <= SHINE_MAX)
            {
                uint16_t pwm = SCALE * (SHINE_MAX - (uint16_t)ss_value);
                setPWM(LED_addr.periph, LED_addr.addr, LED_R, 0x0000, pwm);
                setPWM(LED_addr.periph, LED_addr.addr, LED_G, 0x0000, pwm);
                setPWM(LED_addr.periph, LED_addr.addr, LED_B, 0x0000, pwm);
            }
            else if (have_people == 1 && LED_flag == LED_CLOSE)
            {
                have_people = 0;
                LED_flag = LED_BODY;
                setPWM(LED_addr.periph, LED_addr.addr, LED_R, 0x0000, 0x0C00);
                setPWM(LED_addr.periph, LED_addr.addr, LED_G, 0x0000, 0x0bf1);
                setPWM(LED_addr.periph, LED_addr.addr, LED_B, 0x0000, 0x065d);
            }
            break;
    }
}
